<template>
  <div class="dashboard">
    <!-- 顶部标题行 -->
    <div class="dash-header card">
      <div class="title">工作台</div>
      <div class="date-box">
        <div class="date">{{ today }}</div>
        <div class="weekday">{{ weekday }}</div>
      </div>
    </div>

    <!-- 核心指标 -->
    <div class="kpis card">
      <div class="kpi" v-for="k in kpiItems" :key="k.label">
        <div class="kpi-left">
          <div class="kpi-icon">{{ k.icon }}</div>
          <div class="kpi-meta">
            <div class="kpi-label">{{ k.label }}</div>
            <div class="kpi-sub">{{ k.sub }}</div>
          </div>
        </div>
        <div class="kpi-value">{{ k.value }}</div>
      </div>
    </div>

    <!-- 图表区域 -->
    <div class="chart card">
      <div class="chart-header">
        <div class="tabs">
          <button :class="['tab', chartTab==='sale'?'active':'']" @click="chartTab='sale'">销售统计</button>
          <button :class="['tab', chartTab==='purchase'?'active':'']" @click="chartTab='purchase'">采购统计</button>
        </div>
        <div class="ranges">
          <button :class="['range', range==='7'?'active':'']" @click="range='7'">最近7天</button>
          <button :class="['range', range==='30'?'active':'']" @click="range='30'">最近30天</button>
          <button :class="['range', range==='365'?'active':'']" @click="range='365'">最近1年</button>
        </div>
      </div>
      <div class="chart-body">
        <div ref="chartRef" class="echart"></div>
      </div>
    </div>

    <!-- 中部两列：待审核单据 / 通知公告 -->
    <div class="two-col">
      <div class="card wait-list">
        <div class="card-title">待审核单据</div>
        <div class="wait-grid">
          <div class="wait-item" v-for="w in waitItems" :key="w.label">
            <div class="num" :class="{danger: w.danger}">{{ w.num }}</div>
            <div class="label">{{ w.label }}</div>
          </div>
        </div>
      </div>
      <div class="card notice">
        <div class="card-title">通知公告</div>
        <ul class="notice-list">
          <li v-for="n in notices" :key="n.id">
            <span class="n-title">{{ n.title }}</span>
            <span class="n-time">{{ n.time }}</span>
          </li>
        </ul>
      </div>
    </div>

    <!-- 底部：选项卡 + 表格 -->
    <div class="card table-card">
      <div class="table-tabs">
        <button v-for="t in tableTabs" :key="t" :class="['tab', tableTab===t?'active':'']" @click="tableTab=t">{{ t }}</button>
      </div>
      <div class="table-wrapper">
        <table class="table">
          <thead>
            <tr>
              <th v-for="col in tableColumns" :key="col.key">{{ col.label }}</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="row in currentRows" :key="row._key">
              <td v-for="col in tableColumns" :key="col.key">
                <template v-if="col.key === 'action'">
                  <a href="javascript:void(0)" class="link">查看</a>
                </template>
                <template v-else>
                  {{ row[col.key] }}
                </template>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { MES_workbenchApi } from '@/utils/Interceptors'
import * as echarts from 'echarts'

// 顶部日期
const now = new Date()
const pad = (n: number) => String(n).padStart(2, '0')
const today = `${now.getFullYear()}-${pad(now.getMonth()+1)}-${pad(now.getDate())}`
const weekday = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'][now.getDay()]

// KPI 数据
const kpiItems = ref([
  { icon: '💰', label: '今日销售额(元)', sub: '今日目标(元)', value: '5000.00' },
  { icon: '🧾', label: '今日销售订单(笔)', sub: '今日目标(笔)', value: '100' },
  { icon: '🛒', label: '今日采购额(元)', sub: '今日目标(元)', value: '5000.00' },
  { icon: '🚚', label: '今日出库(件)', sub: '今日目标(件)', value: '5000.00' },
  { icon: '📥', label: '今日入库(件)', sub: '今日目标(件)', value: '5000.00' },
  { icon: '📦', label: '今日库存(件)', sub: '安全库存(件)', value: '5000.00' },
])

// 图表选项（真实数据）
const chartTab = ref<'sale'|'purchase'>('sale')
const range = ref<'7'|'30'|'365'>('7')

// 原始数据与系列
type WorkbenchItem = { id:number; orderAmount:number; orderCount:number; procurementAmount:number; procurementCount:number; plannedStartTime:string }
const raw = ref<WorkbenchItem[]>([])
const xLabels = ref<string[]>([])
const barRaw = ref<number[]>([])
const lineRaw = ref<number[]>([])

// 动态纵轴上限（分6份）
const yLeftMax = ref(600)
const yRightMax = ref(60)
const tickSegments = 6
const leftTicks = computed(() => Array.from({length: tickSegments}, (_,i)=> Math.round(((i+1)*yLeftMax.value)/tickSegments)))
const rightTicks = computed(() => Array.from({length: tickSegments}, (_,i)=> Math.round(((i+1)*yRightMax.value)/tickSegments)))

// ECharts 容器与实例
const chartRef = ref<HTMLDivElement | null>(null)
let chart: echarts.ECharts | null = null

// 根据范围设置柱宽
const barWidth = computed(() => {
  if (range.value === '7') return 32
  if (range.value === '30') return 14
  return 24 // 1年
})

// 不同统计类型的配色
const palette = computed(() => (
  chartTab.value === 'sale'
    ? { bar: '#4da3ff', line: '#36c058' } // 销售：蓝 + 绿色线
    : { bar: '#ff9f43', line: '#e74c3c' } // 采购：橙 + 红色线，区分度更高
))

// ECharts 配置
const chartOption = computed(() => {
  return {
    grid: { left: 56, right: 56, top: 56, bottom: 36 },
    tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
    legend: { data: ['订单额', '订单数'], top: 12, icon: 'roundRect' },
    xAxis: {
      type: 'category',
      data: xLabels.value,
      axisTick: { alignWithLabel: true },
      axisLine: { lineStyle: { color: '#dfe4ea' } },
      axisLabel: { color: '#778' }
    },
    yAxis: [
      {
        type: 'value', name: '单位（元）', min: 0, max: yLeftMax.value,
        splitNumber: 6,
        axisLabel: { color: '#778' },
        splitLine: { lineStyle: { color: '#eef2f6' } }
      },
      {
        type: 'value', name: '单位（笔）', min: 0, max: yRightMax.value,
        splitNumber: 6, position: 'right',
        axisLabel: { color: '#778' },
        splitLine: { show: false }
      }
    ],
    series: [
      {
        name: '订单额', type: 'bar', data: barRaw.value,
        barWidth: barWidth.value,
        itemStyle: { color: palette.value.bar, borderRadius: [4,4,0,0] }
      },
      {
        name: '订单数', type: 'line', yAxisIndex: 1, data: lineRaw.value,
        smooth: true, symbol: 'circle', symbolSize: 6,
        lineStyle: { color: palette.value.line, width: 2.5 },
        itemStyle: { color: palette.value.line }
      }
    ]
  }
})

// 根据当前tab设置系列与纵轴
function applySeries() {
  if (!raw.value?.length) { barRaw.value = []; lineRaw.value = []; xLabels.value = []; return }
  const useAmount = chartTab.value === 'sale' ? 'orderAmount' : 'procurementAmount'
  const useCount  = chartTab.value === 'sale' ? 'orderCount'  : 'procurementCount'
  let amounts: number[] = []
  let counts: number[] = []

  if (range.value === '365') {
    // 同月聚合：1~12 月各一个柱/点
    const aByMonth = Array(12).fill(0)
    const cByMonth = Array(12).fill(0)
    raw.value.forEach(r => {
      const d = new Date(r.plannedStartTime)
      const m = isNaN(d.getTime()) ? undefined : d.getMonth() // 0-11
      if (m !== undefined) {
        aByMonth[m] += Number(r[useAmount] || 0)
        cByMonth[m] += Number(r[useCount] || 0)
      }
    })
    amounts = aByMonth
    counts = cByMonth
    barRaw.value = amounts
    lineRaw.value = counts
    xLabels.value = Array.from({length:12}, (_,i)=> `${i+1}月`)
  } else if (range.value === '7') {
    // 最近7天：同一天聚合，仅保留近7天
    const mapA: Record<string, number> = {}
    const mapC: Record<string, number> = {}
    const dayKey = (iso:string) => {
      const d = new Date(iso)
      if (isNaN(d.getTime())) return ''
      const P = (n:number)=> String(n).padStart(2,'0')
      return `${d.getFullYear()}-${P(d.getMonth()+1)}-${P(d.getDate())}`
    }
    raw.value.forEach(r => {
      const key = dayKey(r.plannedStartTime)
      if (!key) return
      mapA[key] = (mapA[key] || 0) + Number(r[useAmount] || 0)
      mapC[key] = (mapC[key] || 0) + Number(r[useCount] || 0)
    })
    const days = Object.keys(mapA).sort() // 升序
    const last7 = days.slice(-7)
    amounts = last7.map(d => mapA[d] || 0)
    counts  = last7.map(d => mapC[d] || 0)
    barRaw.value = amounts
    lineRaw.value = counts
    xLabels.value = Array.from({ length: last7.length }, (_, i) => String(i + 1))
  } else if (range.value === '30') {
    // 最近30天：同一天聚合，仅保留近30天
    const mapA: Record<string, number> = {}
    const mapC: Record<string, number> = {}
    const dayKey = (iso:string) => {
      const d = new Date(iso)
      if (isNaN(d.getTime())) return ''
      const P = (n:number)=> String(n).padStart(2,'0')
      return `${d.getFullYear()}-${P(d.getMonth()+1)}-${P(d.getDate())}`
    }
    raw.value.forEach(r => {
      const key = dayKey(r.plannedStartTime)
      if (!key) return
      mapA[key] = (mapA[key] || 0) + Number(r[useAmount] || 0)
      mapC[key] = (mapC[key] || 0) + Number(r[useCount] || 0)
    })
    const days = Object.keys(mapA).sort()
    const last30 = days.slice(-30)
    amounts = last30.map(d => mapA[d] || 0)
    counts  = last30.map(d => mapC[d] || 0)
    barRaw.value = amounts
    lineRaw.value = counts
    xLabels.value = Array.from({ length: last30.length }, (_, i) => String(i + 1))
  } else {
    // 兜底：逐条展示
    amounts = raw.value.map(r => r[useAmount] as number)
    counts  = raw.value.map(r => r[useCount] as number)
    barRaw.value = amounts
    lineRaw.value = counts
    xLabels.value = Array.from({ length: raw.value.length }, (_, i) => String(i + 1))
  }

  // 纵轴上限：向上取整到合适步长
  const maxA = Math.max(1, ...amounts)
  const maxC = Math.max(1, ...counts)
  const ceilTo = (v:number, step:number) => Math.ceil(v/step)*step
  yLeftMax.value  = ceilTo(maxA, 100) || 100
  yRightMax.value = ceilTo(maxC, 10)  || 10
}

// 拉取后端数据
async function loadData() {
  const map: Record<typeof range.value, string> = { '7': '7d', '30': '1m', '365': '1y' }
  const body = { range: map[range.value] }
  const { data } = await MES_workbenchApi.post('/api/Workbench/data-statistics', body)
  if (data?.code === 200 && Array.isArray(data.data)) {
    raw.value = data.data
    applySeries()
    await nextTick()
    renderChart()
  }
}

watch(range, () => { loadData() })
watch(chartTab, () => { applySeries(); renderChart() })
watch([barWidth, yLeftMax, yRightMax, () => xLabels.value, () => barRaw.value, () => lineRaw.value], () => {
  renderChart()
})

// 首次加载改为在 onMounted 中统一触发，避免重复请求

function renderChart() {
  if (!chartRef.value) return
  if (!chart) {
    chart = echarts.init(chartRef.value)
    window.addEventListener('resize', resize)
  }
  chart.setOption(chartOption.value as any, true)
}

function resize() { chart && chart.resize() }

onMounted(() => { if (raw.value.length) renderChart() })
onBeforeUnmount(() => {
  window.removeEventListener('resize', resize)
  if (chart) { chart.dispose(); chart = null }
})

// 待审核单据
const waitItems = ref([
  { label: '采购订单', num: 0 },
  { label: '销售订单', num: 5, danger: true },
  { label: '入库单', num: 0 },
  { label: '出库单', num: 3 },
  { label: '采购单', num: 2 },
  { label: '发出单', num: 1 },
  { label: '开票单', num: 6, danger: true },
  { label: '请购单', num: 0 },
])

// 通知公告（真实数据）
type NoticeItem = { id: number; title: string; time: string }
const notices = ref<NoticeItem[]>([])

function fmtDateTime(iso: string) {
  const d = new Date(iso)
  if (isNaN(d.getTime())) return ''
  const P = (n:number)=> String(n).padStart(2,'0')
  return `${d.getFullYear()}-${P(d.getMonth()+1)}-${P(d.getDate())} ${P(d.getHours())}:${P(d.getMinutes())}:${P(d.getSeconds())}`
}

async function loadNotices() {
  try {
    const { data } = await MES_workbenchApi.get('/api/Workbench/notices/latest')
    if (data?.code === 200 && Array.isArray(data.data)) {
      notices.value = data.data.map((n:any) => ({
        id: n.noticeId,
        title: n.noticeContent,
        time: fmtDateTime(n.receiveTime)
      }))
    }
  } catch (e) {
    // 保持静默失败，避免打断页面渲染
  }
}

// 底部表格
const tableTabs = ['订单交付明细','工单提醒','工序提醒','即将到期物品','已到期物品']
const route = useRoute()
const router = useRouter()
const tableTab = ref<string>(tableTabs[0])

// 1) 订单交付明细（原有）
type DeliveryRow = { _key: string; id: string; code: string; name: string; type: string; due: string; action?: string }
const tableRows = ref<DeliveryRow[]>([])

// 2) 工单提醒（图2）
type WorkAlertRow = { _key: string; billNo: string; product: string; status: string; planStart: string; planEnd: string; owner: string; action?: string }
const workAlertRows = ref<WorkAlertRow[]>([])

// 3) 工序提醒（真实数据）
type ProcessAlertRow = { _key: string; billNo: string; processName: string; status: string; planStart: string; planEnd: string; owner: string; action?: string }
const processAlertRows = ref<ProcessAlertRow[]>([])

// 4) 即将到期物品（图：物品编码/物品名称/批次号/生产日期/到期日期/仓库/库存数量，真实数据）
type SoonExpireRow = { _key: string; itemCode: string; itemName: string; batchNo: string; mfgDate: string; expDate: string; warehouse: string; stockQty: number; action?: string }
const soonExpireRows = ref<SoonExpireRow[]>([])

// 5) 已到期物品（列同“即将到期物品”，真实数据）
type ExpiredRow = { _key: string; itemCode: string; itemName: string; batchNo: string; mfgDate: string; expDate: string; warehouse: string; stockQty: number; action?: string }
const expiredRows = ref<ExpiredRow[]>([])

// 列定义与当前数据
const tableColumns = computed(() => {
  if (tableTab.value === '工单提醒') {
    return [
      { key: 'billNo', label: '单据编号' },
      { key: 'product', label: '生产物品' },
      { key: 'status', label: '单据状态' },
      { key: 'planStart', label: '计划开始时间' },
      { key: 'planEnd', label: '计划结束时间' },
      { key: 'owner', label: '负责人' },
      { key: 'action', label: '操作' },
    ]
  }
  if (tableTab.value === '工序提醒') {
    return [
      { key: 'billNo', label: '单据编号' },
      { key: 'processName', label: '工序名称' },
      { key: 'status', label: '状态' },
      { key: 'planStart', label: '计划时间' },
      { key: 'planEnd', label: '计划结束时间' },
      { key: 'owner', label: '负责人' },
      { key: 'action', label: '操作' },
    ]
  }
  if (tableTab.value === '即将到期物品') {
    return [
      { key: 'itemCode', label: '物品编码' },
      { key: 'itemName', label: '物品名称' },
      { key: 'batchNo', label: '批次号' },
      { key: 'mfgDate', label: '生产日期' },
      { key: 'expDate', label: '到期日期' },
      { key: 'warehouse', label: '仓库' },
      { key: 'stockQty', label: '库存数量' },
      { key: 'action', label: '操作' },
    ]
  }
  if (tableTab.value === '已到期物品') {
    return [
      { key: 'itemCode', label: '物品编码' },
      { key: 'itemName', label: '物品名称' },
      { key: 'batchNo', label: '批次号' },
      { key: 'mfgDate', label: '生产日期' },
      { key: 'expDate', label: '到期日期' },
      { key: 'warehouse', label: '仓库' },
      { key: 'stockQty', label: '库存数量' },
      { key: 'action', label: '操作' },
    ]
  }
  // 订单交付明细（默认）
  return [
    { key: 'id', label: '单据编号' },
    { key: 'code', label: '物料编码' },
    { key: 'name', label: '物料名称' },
    { key: 'type', label: '单据类型' },
    { key: 'due', label: '交付日期' },
    { key: 'action', label: '操作' },
  ]
})

const currentRows = computed<any[]>(() => {
  if (tableTab.value === '工单提醒') return workAlertRows.value
  if (tableTab.value === '工序提醒') return processAlertRows.value
  if (tableTab.value === '即将到期物品') return soonExpireRows.value
  if (tableTab.value === '已到期物品') return expiredRows.value
  return tableRows.value
})

function fmtDate(iso: string) {
  const d = new Date(iso)
  if (isNaN(d.getTime())) return ''
  const P = (n:number)=> String(n).padStart(2,'0')
  return `${d.getFullYear()}-${P(d.getMonth()+1)}-${P(d.getDate())}`
}

async function loadOrderDeliveries() {
  try {
    const { data } = await MES_workbenchApi.get('/api/Workbench/order-delivery-reminders/latest')
    if (data?.code === 200 && Array.isArray(data.data)) {
      const rows: DeliveryRow[] = data.data.slice(0,4).map((it:any, idx:number) => ({
        _key: String(idx + 1),
        id: it.documentNo,
        code: it.documentTitle,
        name: it.documentType,
        type: it.documentStatus, // 接口未提供物料编码字段，先占位
        due: fmtDate(it.deliveryTime)
      }))
      tableRows.value = rows
    }
  } catch (e) {
    // 静默失败
  }
}

// 工单提醒 - 真实数据
async function loadWorkAlerts() {
  try {
    const { data } = await MES_workbenchApi.get('/api/Workbench/work-order-reminders/latest')
    if (data?.code === 200 && Array.isArray(data.data)) {
      const rows: WorkAlertRow[] = data.data.slice(0,4).map((it:any, idx:number) => ({
        _key: String(idx + 1),
        billNo: it.documentNo,
        product: it.productionItem,
        status: it.documentStatus,
        planStart: fmtDateTime(it.plannedStartTime),
        planEnd: fmtDateTime(it.plannedEndTime),
        owner: it.owner
      }))
      workAlertRows.value = rows
    }
  } catch (e) {
    // 静默失败
  }
}

// 已到期物品 - 真实数据
async function loadExpiredItems() {
  try {
    const { data } = await MES_workbenchApi.get('/api/Workbench/items-approaching-expiry/expired')
    if (data?.code === 200 && Array.isArray(data.data)) {
      const rows: ExpiredRow[] = data.data.slice(0,4).map((it:any, idx:number) => ({
        _key: String(idx + 1),
        itemCode: it.itemCode,
        itemName: it.itemName,
        batchNo: it.batchNo,
        mfgDate: fmtDate(it.productionDate),
        expDate: fmtDate(it.expiryDate),
        warehouse: it.warehouse,
        stockQty: Number(it.stockQuantity || 0),
      }))
      expiredRows.value = rows
    }
  } catch (e) {
    // 静默失败
  }
}

// 工序提醒 - 真实数据
async function loadProcessAlerts() {
  try {
    const { data } = await MES_workbenchApi.get('/api/Workbench/process-step-reminders/latest')
    if (data?.code === 200 && Array.isArray(data.data)) {
      const rows: ProcessAlertRow[] = data.data.slice(0,4).map((it:any, idx:number) => ({
        _key: String(idx + 1),
        billNo: it.documentNo,
        processName: it.processName,
        status: it.documentStatus,
        planStart: fmtDateTime(it.plannedStartTime),
        planEnd: fmtDateTime(it.plannedEndTime),
        owner: it.owner,
      }))
      processAlertRows.value = rows
    }
  } catch (e) {
    // 静默失败
  }
}

// 即将到期物品 - 真实数据
async function loadSoonExpireItems() {
  try {
    const { data } = await MES_workbenchApi.get('/api/Workbench/items-approaching-expiry/not-expired')
    if (data?.code === 200 && Array.isArray(data.data)) {
      const rows: SoonExpireRow[] = data.data.slice(0,4).map((it:any, idx:number) => ({
        _key: String(idx + 1),
        itemCode: it.itemCode,
        itemName: it.itemName,
        batchNo: it.batchNo,
        mfgDate: fmtDate(it.productionDate),
        expDate: fmtDate(it.expiryDate),
        warehouse: it.warehouse,
        stockQty: Number(it.stockQuantity || 0),
      }))
      soonExpireRows.value = rows
    }
  } catch (e) {
    // 静默失败
  }
}

// 接收路由查询，支持 /about?tab=工单提醒 直接定位到该页签
onMounted(() => {
  const qTab = (route.query.tab as string) || ''
  if (qTab && tableTabs.includes(qTab)) {
    tableTab.value = qTab
  }
  loadData()
  loadNotices()
  loadOrderDeliveries()
  loadWorkAlerts() // 加载工单提醒
  loadProcessAlerts() // 加载工序提醒
  loadExpiredItems() // 加载已到期物品
  loadSoonExpireItems() // 加载即将到期物品
})

// 同步 tab 到路由查询，便于通过地址栏分享/跳转
watch(tableTab, (val) => {
  const q = { ...route.query, tab: val }
  router.replace({ path: route.path, query: q })
})
</script>

<style scoped>
/* 页面基础 */
.dashboard { padding: 16px 18px 24px; background: #f6f8fb; min-height: 100%; box-sizing: border-box; font-size: 12px; }
.dashboard { max-width: 1120px; margin: 0 auto; }
.dashboard { 
  /* 使 AboutView 自身成为滚动容器，避免影响全局滚动条 */
  max-height: 100vh; 
  overflow: auto;
  /* 隐藏滚动条但保留滚动（Firefox/IE/Edge legacy） */
  scrollbar-width: none;      /* Firefox */
  -ms-overflow-style: none;   /* IE 10+ / Edge Legacy */
}

/* WebKit（Edge/Chrome/Safari）更透明更细的滚动条，仅作用于 AboutView */
/* 隐藏 WebKit 滚动条（Edge/Chrome/Safari） */
.dashboard::-webkit-scrollbar { width: 0; height: 0; display: none; }
.card { background: #fff; border-radius: 10px; box-shadow: 0 2px 10px rgba(31,45,61,.05); padding: 14px; border: 1px solid #eef1f6; }

/* 标题行 */
.dash-header { display:flex; align-items:center; justify-content:space-between; margin-bottom: 14px; }
.dash-header .title { font-size: 16px; font-weight: 700; color:#2d3a4a; }
.dash-header .date-box { color:#666; display:flex; gap:8px; }
.dash-header .weekday { color:#999; }

/* KPI 指标 */
.kpis { display:grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap:0; margin-bottom: 22px; padding: 6px 6px; }
.kpi { display:grid; grid-template-columns: 32px 1fr; grid-template-rows: auto auto; column-gap:10px; align-items:center; border:none; background: transparent; border-radius:0; padding:12px 16px; min-height:72px; position:relative; }
.kpi::after { content: ""; position:absolute; right:0; top:50%; transform: translateY(-50%); height:36px; width:1px; background:#eef2f6; }
.kpi:last-child::after { display:none; }
.kpi-left { display:contents; }
.kpi-icon { grid-column:1; grid-row: 1 / span 2; width:30px; height:30px; display:flex; align-items:center; justify-content:center; background:#f3f6fb; border-radius:8px; font-size:14px; color:#9aa7b3; }
.kpi-label { grid-column:2; grid-row:1; font-size:12px; color:#5a6b7b; font-weight:600; line-height:1.2; }
.kpi-sub { font-size:12px; color:#999; display:none; }
.kpi-value { grid-column:2; grid-row:2; font-weight:800; color:#2b7de2; font-size:16px; line-height:1.2; justify-self:start; }

/* 图表 */
.chart { margin-bottom: 28px; }
.chart-header { display:flex; align-items:center; justify-content:space-between; margin-bottom: 8px; }
.tabs .tab, .ranges .range { border:1px solid #e3e8ef; background:#fff; color:#333; padding:4px 10px; margin-right:8px; border-radius:8px; cursor:pointer; line-height:1; height:28px; font-size:12px; }
.tabs .tab:hover, .ranges .range:hover { border-color:#bfc8d8; }
.tabs .tab.active, .ranges .range.active { background:#2b7de2; color:#fff; border-color:#2b7de2; box-shadow: 0 2px 6px rgba(43,125,226,.2); }
.chart-body {
  position:relative; 
  padding: 8px 8px 20px; 
  background: #fff;
  border-radius: 10px;
}
.echart { 
  width:100%; 
  height:360px; 
  background: linear-gradient(#fff, #fafbfd); 
  border:1px solid #eef1f6; 
  border-radius:10px; 
}
.legend { 
  position:absolute; 
  top:8px; 
  left:50%; 
  transform: translateX(-50%); 
  display:flex; 
  gap:16px; 
  color:#666; 
  font-size:12px; 
  align-items:center; 
}
.legend .bar { 
  display:inline-block; 
  width:12px; 
  height:12px; 
  background:#4da3ff; 
  border-radius:2px; 
  margin-right:6px; 
}
.legend .line { 
  display:inline-block; 
  width:12px; 
  height:2px; 
  background:#36c058; 
  margin-right:6px; 
  position:relative; 
  top:-5px; 
}

/* 两列区域 */
.two-col { display:grid; grid-template-columns: 3fr 2fr; gap:22px; margin-bottom: 22px; }
.card-title { font-weight:600; margin-bottom:10px; }
.wait-grid { display:grid; grid-template-columns: repeat(6, 1fr); gap:16px; }
.wait-item .num { font-size:15px; font-weight:700; color:#2b7de2; }
.wait-item .num.danger { color:#e53935; }
.wait-item .label { font-size:12px; color:#888; }
.notice-list { list-style:none; padding:0; margin:0; }
.notice-list li { display:flex; justify-content:space-between; padding:8px 6px; border-bottom:1px dashed #eef1f6; color:#555; align-items:center; }
.notice-list .n-time { color:#999; }

/* 表格 */
.table-card { margin-top: 6px; }
.table-tabs { margin-bottom:8px; border-bottom:1px solid #eef1f6; padding-bottom:4px; }
.table-tabs .tab { border:none; background:transparent; padding:6px 8px; margin-right:10px; cursor:pointer; color:#666; border-bottom:2px solid transparent; font-size:12px; }
.table-tabs .tab.active { color:#2b7de2; border-color:#2b7de2; font-weight:600; }
.table-wrapper { border:1px solid #eef1f6; border-radius:10px; overflow:auto; }
.table { width:100%; border-collapse:collapse; }
.table th, .table td { padding:9px 10px; border-bottom:1px solid #f0f2f5; white-space:nowrap; font-size:12px; }
.table th { background:#fafbfd; color:#666; text-align:left; font-weight:600; position:sticky; top:0; z-index:1; }
.table .link { color:#2b7de2; text-decoration:none; }
.table tbody tr:nth-child(even) { background: #fafbfd; }

/* 响应式 */
@media (max-width: 1400px) {
  .kpis { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
  .wait-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 768px) {
  .two-col { grid-template-columns: 1fr; }
  .kpis { grid-template-columns: repeat(2, 1fr); gap:12px; }
  .wait-grid { grid-template-columns: repeat(2, 1fr); }
}
</style>
